//
// RichElement.cpp
//
// Copyright (c) Shareaza Development Team, 2002-2005.
// This file is part of SHAREAZA (www.shareaza.com)
//
// Shareaza is free software; you can redistribute it
// and/or modify it under the terms of the GNU General Public License
// as published by the Free Software Foundation; either version 2 of
// the License, or (at your option) any later version.
//
// Shareaza is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Shareaza; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
//

#include "StdAfx.h"
#include "Shareaza.h"
#include "Settings.h"
#include "RichDocument.h"
#include "RichElement.h"
#include "RichFragment.h"

#include "CoolInterface.h"
#include "ImageServices.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif


//////////////////////////////////////////////////////////////////////
// CRichElement construction

CRichElement::CRichElement(int nType, LPCTSTR pszText, LPCTSTR pszLink, DWORD nFlags, int nGroup)
{
	m_pDocument	= NULL;
	m_nType		= nType;
	m_nFlags	= nFlags;
	m_nGroup	= nGroup;
	m_hImage	= NULL;

	if ( m_nType == retHeading )
	{
		m_nType = retText;
		m_nFlags |= retfHeading;
	}

	if ( pszText != NULL )
	{
		if ( ( m_nType == retBitmap || m_nType == retIcon ) && HIWORD(pszText) == 0 )
		{
			m_sText.Format( _T("%lu"), (DWORD)pszText );
		}
		else
		{
			m_sText = pszText;
		}
	}

	if ( pszLink != NULL ) m_sLink = pszLink;
}

CRichElement::~CRichElement()
{
	if ( m_hImage != NULL )
	{
		if ( m_nType == retBitmap )
		{
			DeleteObject( (HBITMAP)m_hImage );
			m_hImage = NULL;
		}
		else if ( m_nType == retIcon )
		{
			DestroyIcon( (HICON)m_hImage );
			m_hImage = NULL;
		}
	}
}

//////////////////////////////////////////////////////////////////////
// CRichElement editing

void CRichElement::Show(BOOL bShow)
{
	if ( bShow == ( ( m_nFlags & retfHidden ) > 0 ) )
	{
		m_nFlags |= retfHidden;
		if ( bShow ) m_nFlags &= ~retfHidden;
		m_pDocument->m_nCookie++;
	}
}

void CRichElement::SetText(LPCTSTR pszText)
{
	if ( m_sText != pszText )
	{
		m_sText = pszText;
		m_pDocument->m_nCookie++;
	}
}

void CRichElement::SetFlags(DWORD nFlags, DWORD nMask)
{
	DWORD nNew = ( m_nFlags & ~nMask ) | ( nFlags & nMask );

	if ( nNew != m_nFlags )
	{
		m_nFlags = nNew;
		m_pDocument->m_nCookie++;
	}
}

//////////////////////////////////////////////////////////////////////
// CRichElement delete

void CRichElement::Delete()
{
	if ( m_pDocument ) m_pDocument->Remove( this );
	delete this;
}

//////////////////////////////////////////////////////////////////////
// CRichElement setup for paint

void CRichElement::PrePaint(CDC* pDC, BOOL bHover)
{
	if ( m_pDocument->m_fntNormal.m_hObject == NULL ) m_pDocument->CreateFonts();

	CFont* pFont = &m_pDocument->m_fntNormal;

	switch ( m_nType )
	{
	case retText:
		if ( m_nFlags & retfColour )
			pDC->SetTextColor( m_cColour );
		else
			pDC->SetTextColor( m_pDocument->m_crText );
		pFont = &m_pDocument->m_fntNormal;
		break;
	case retLink:
		if ( m_nFlags & retfColour )
			pDC->SetTextColor( m_cColour );
		else
			pDC->SetTextColor( bHover ? m_pDocument->m_crHover : m_pDocument->m_crLink );
		pFont = &m_pDocument->m_fntUnder;
		break;
	case retBitmap:
		PrePaintBitmap( pDC );
		pFont = NULL;
		break;
	case retIcon:
		PrePaintIcon( pDC );
		pFont = NULL;
		break;
	case retEmoticon:
		_stscanf( m_sText, _T("%i"), &m_hImage );
		pFont = NULL;
		break;
	case retCmdIcon:
		if ( UINT nID = CoolInterface.NameToID( m_sText ) )
		{
			m_hImage = CoolInterface.ImageForID( nID );
		}
		break;
	default:
		pFont = NULL;
		break;
	}

	if ( m_nFlags & retfBold )
	{
		if ( m_nFlags & retfUnderline ) pFont = &m_pDocument->m_fntBoldUnder;
		else pFont = &m_pDocument->m_fntBold;
	}
	else if ( m_nFlags & retfItalic )
	{
		pFont = &m_pDocument->m_fntItalic;
	}
	else if ( m_nFlags & retfUnderline )
	{
		pFont = &m_pDocument->m_fntUnder;
	}
	else if ( m_nFlags & retfHeading )
	{
		pFont = &m_pDocument->m_fntHeading;
		pDC->SetTextColor( m_pDocument->m_crHeading );
	}

	if ( pFont ) pDC->SelectObject( pFont );
}

void CRichElement::PrePaintBitmap(CDC* pDC)
{
	if ( m_hImage != NULL ) return;

	if ( _tcsnicmp( m_sText, _T("res:"), 4 ) == 0 )
	{
		LPCTSTR pszDot = _tcschr( m_sText, '.' );
		CBitmap pBitmap;
		UINT nID;

		if ( pszDot == NULL || _stscanf( (LPCTSTR)m_sText + 4, _T("%lu"), &nID ) != 1 ) return;

		if ( CImageServices::LoadBitmap( &pBitmap, nID, pszDot + 1 ) )
		{
			m_hImage = (DWORD)pBitmap.Detach();
		}
	}
	else
	{
		CString strFile = Settings.General.Path + '\\' + m_sText;
		HBITMAP hBitmap = (HBITMAP)LoadImage( AfxGetResourceHandle(),
			strFile, IMAGE_BITMAP, 0, 0, LR_LOADFROMFILE );
		m_hImage = theApp.m_bRTL ? (DWORD)CreateMirroredBitmap( hBitmap ) : (DWORD)hBitmap;
	}
}

void CRichElement::PrePaintIcon(CDC* pDC)
{
	if ( m_hImage != NULL || m_sText.IsEmpty() ) return;

	UINT nID, nWidth = 16, nHeight = 16;
	_stscanf( m_sText, _T("%lu.%i.%i"), &nID, &nWidth, &nHeight );

	HICON hIcon = CoolInterface.ExtractIcon( nID );
	m_hImage = theApp.m_bRTL ? (DWORD)CreateMirroredIcon( hIcon ) : (DWORD)hIcon;

	if ( m_hImage == NULL )
	{
		hIcon = (HICON)LoadImage( AfxGetResourceHandle(),
			MAKEINTRESOURCE( nID ), IMAGE_ICON, nWidth, nHeight, 0 );
		m_hImage = theApp.m_bRTL ? (DWORD)CreateMirroredIcon( hIcon ) : (DWORD)hIcon;
	}
}

//////////////////////////////////////////////////////////////////////
// CRichElement dimensions

CSize CRichElement::GetSize()
{
	CSize sz( 0, 0 );

	if ( m_nType == retGap )
	{
		_stscanf( m_sText, _T("%lu"), &sz.cx );
	}
	else if ( m_nType == retBitmap && m_hImage != NULL )
	{
		BITMAP pInfo;
		GetObject( (HBITMAP)m_hImage, sizeof(pInfo), &pInfo );

		sz.cx = pInfo.bmWidth;
		sz.cy = pInfo.bmHeight;
	}
	else if ( m_nType == retIcon )
	{
		sz.cx = sz.cy = 16;
		UINT nID;
		_stscanf( m_sText, _T("%lu.%i.%i"), &nID, &sz.cx, &sz.cy );
	}
	else if ( m_nType == retEmoticon || m_nType == retCmdIcon )
	{
		sz.cx = sz.cy = 16;
	}
	else if ( m_nType == retAnchor )
	{
		sz.cx = sz.cy = 16;
		_stscanf( m_sText, _T("%i.%i"), &sz.cx, &sz.cy );
	}

	return sz;
}
